(* Returns the tail of a string *)
let stail = function
	s -> (String.sub s 1  ((String.length s) - 1))

(* Returns the head of a string *)
let shead = function
	s -> (String.make 1 s.[0])

(*fonction qui transforme une chaine de characteres en
la liste des elements de cette chaine
qui sont separes d'espaces *)
(*elle peut convertir les mots reconnus dans la chaine a
 l'aide de la fonction convert*)
let arg2list arg convert =
	let rec aux acc = function
		"" -> (if acc <> "" then
				(convert acc)::[]
			else
				[])
		|s when (s.[0] = ' ') -> (if acc <> "" then
						(convert acc)::(aux "" (stail s))
		   	   		  else
						aux "" (stail s))
		|s -> aux (acc^(shead s))  (stail s)
	in
	aux "" arg

(*Separe en un couple le premier caractere de la
chaine et la suite de la chaine*)
let split s =
	if s <> "" then
		let rec aux = function
	 		s when (s.[0] = ' ') -> aux (stail s)
			|s -> (shead s , stail s)
		in
		aux s
	else
		failwith "Le fichier .obj est corrompu"


(* Reads a vertex from the obj file *)
let readv = function
	arg ->(match arg2list arg (float_of_string) with
		x::y::z::_ -> (x,y,z)
		|_ -> failwith "Le fichier .obj est corrompu")


(* Reads a face from the obj file *)
let readf = function arg -> arg2list arg (int_of_string)


(* Merges vArray and fArray to one array *)
let mergeVF = function
(vArray,fArray) ->
	let vnul = (0.,0.,0.) in
	let res = Array.make (Array.length fArray) (vnul,vnul,vnul) in
	let getVertices = function
		n ->
                	(let nface = fArray.(n) in
                	(vArray.((List.nth nface 0) - 1),
                 	vArray.((List.nth nface 1) -1),
                 	vArray.((List.nth nface 2) - 1)))
	in

	begin
		for i = 0 to ((Array.length fArray) -1) do
			res.(i) <- getVertices i;
		done;
	end; res
(* Reads a given obj file *)
let readObj filename =
	let f = open_in (filename) in
	let (vList, fList) =  (ref [],ref []) in
	let keep_going = ref true in
	while !keep_going do
		try
			let line = input_line f in
	                let (fl,arg) = split line in
        	        if fl = "v" then
                	        vList := (readv arg)::!vList
                	else if fl = "f" then
                        	fList := (readf arg)::!fList
                	else
                        	failwith "le fichier .obj est corrompu"
		with
			End_of_file -> keep_going := false
	done;
		let vertices = Array.of_list (List.rev !vList) in
		let faces = Array.of_list (List.rev !fList) in
		close_in f;
                (mergeVF (vertices,
                         faces),vertices,faces)
